package com.kexio.user.dto;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.kexio.common.exception.BusinessException;
import com.kexio.common.page.PageQuery;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

/**
 * 角色统一DTO
 * 
 * 支持角色的创建、更新、响应、分页查询等全部功能
 * 通过验证分组区分不同用途，继承PageQuery支持分页
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RoleDTO extends PageQuery implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    // ==================== 验证分组接口 ====================
    
    /**
     * 创建角色验证分组
     */
    public interface CreateGroup {}
    
    /**
     * 更新角色验证分组
     */
    public interface UpdateGroup {}
    
    // ==================== 基本字段 ====================
    
    /**
     * 角色ID（响应时使用）
     */
    private String roleId;
    
    /**
     * 租户ID
     */
    private String tenantId;
    
    /**
     * 角色编码（创建时必填，更新时通常不变）
     */
    @NotBlank(message = "角色编码不能为空", groups = CreateGroup.class)
    @Size(min = 2, max = 64, message = "角色编码长度必须在2-64个字符之间", groups = {CreateGroup.class, UpdateGroup.class})
    private String roleCode;
    
    /**
     * 角色名称
     */
    @NotBlank(message = "角色名称不能为空", groups = CreateGroup.class)
    @Size(min = 2, max = 64, message = "角色名称长度必须在2-64个字符之间", groups = {CreateGroup.class, UpdateGroup.class})
    private String roleName;
    
    /**
     * 角色描述
     */
    @Size(max = 500, message = "角色描述长度不能超过500个字符", groups = {CreateGroup.class, UpdateGroup.class})
    private String description;
    
    /**
     * 数据权限范围
     * ALL - 全部数据权限
     * DEPT - 本部门数据权限  
     * DEPT_AND_CHILD - 本部门及以下数据权限
     * SELF - 仅本人数据权限
     * CUSTOM - 自定义数据权限
     */
    private String dataScope;
    
    /**
     * 自定义部门权限（当dataScope为CUSTOM时使用）
     */
    private List<String> deptIds;
    
    /**
     * 角色状态：1-启用，0-禁用
     */
    private Integer status;
    
    /**
     * 角色排序
     */
    private Integer orderNo;
    
    // ==================== 扩展字段（主要用于响应） ====================
    
    /**
     * 创建时间
     */
    private LocalDateTime createTime;
    
    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
    
    /**
     * 创建者ID
     */
    private String createBy;
    
    /**
     * 创建者名称
     */
    private String createdByName;
    
    /**
     * 更新者ID
     */
    private String updateBy;
    
    /**
     * 更新者名称
     */
    private String updatedByName;
    
    /**
     * 拥有此角色的用户数量
     */
    private Long userCount;
    
    /**
     * 角色拥有的权限数量
     */
    private Integer permissionCount;
    
    /**
     * 角色权限列表（详细信息时返回）
     */
    private List<String> permissionIds;
    
    // ==================== 操作字段 ====================
    
    /**
     * 操作备注（创建/更新时使用）
     */
    @Size(max = 200, message = "操作备注长度不能超过200个字符", groups = {CreateGroup.class, UpdateGroup.class})
    private String operatorNote;
    
    // ==================== 构造函数 ====================
    
    public RoleDTO() {
        this.status = 1; // 默认启用
        this.orderNo = 0; // 默认排序
    }
    
    public RoleDTO(String roleCode, String roleName) {
        this();
        this.roleCode = roleCode;
        this.roleName = roleName;
    }
    
    // ==================== 静态工厂方法 ====================
    
    /**
     * 创建用于新增角色的DTO
     */
    public static RoleDTO forCreate(String roleCode, String roleName) {
        RoleDTO dto = new RoleDTO(roleCode, roleName);
        return dto;
    }
    
    /**
     * 创建用于更新角色的DTO
     */
    public static RoleDTO forUpdate() {
        return new RoleDTO();
    }
    
    
    // ==================== 便捷方法 ====================
    
    /**
     * 判断是否有描述
     */
    public boolean hasDescription() {
        return StringUtils.hasText(description);
    }
    
    /**
     * 判断是否有自定义部门权限
     */
    public boolean hasCustomDepts() {
        return deptIds != null && !deptIds.isEmpty();
    }
    
    /**
     * 判断角色是否为启用状态
     */
    public boolean isEnabled() {
        return Integer.valueOf(1).equals(status);
    }
    
    /**
     * 获取自定义部门数量
     */
    public int getCustomDeptCount() {
        return hasCustomDepts() ? deptIds.size() : 0;
    }
    
    /**
     * 判断是否为系统内置角色
     */
    public boolean isSystemRole() {
        return roleCode != null && (roleCode.startsWith("SYSTEM_") || roleCode.startsWith("ADMIN"));
    }
    
    /**
     * 验证并清理输入数据
     */
    public void validateAndClean() {
        if (roleCode != null) {
            roleCode = roleCode.trim().toUpperCase();
        }
        
        if (roleName != null) {
            roleName = roleName.trim();
        }
        
        if (description != null) {
            description = description.trim();
            if (description.isEmpty()) {
                description = null;
            }
        }
        
        if (dataScope != null) {
            dataScope = dataScope.trim().toUpperCase();
        }
        
        if (operatorNote != null) {
            operatorNote = operatorNote.trim();
            if (operatorNote.isEmpty()) {
                operatorNote = null;
            }
        }
        
        if (status == null) {
            status = 1;
        }
        
        if (orderNo == null) {
            orderNo = 0;
        }
    }
    
    /**
     * 判断是否有创建相关的必填字段
     */
    public boolean hasCreateRequiredFields() {
        return StringUtils.hasText(roleCode) && StringUtils.hasText(roleName);
    }
    
    /**
     * 判断是否有任何更新内容
     */
    public boolean hasAnyUpdateFields() {
        return roleName != null || description != null || dataScope != null ||
               status != null || orderNo != null || deptIds != null;
    }
    
    // ==================== Getter/Setter ====================
    
    public String getRoleId() {
        return roleId;
    }
    
    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }
    
    public String getTenantId() {
        return tenantId;
    }
    
    public void setTenantId(String tenantId) {
        this.tenantId = tenantId;
    }
    
    public String getRoleCode() {
        return roleCode;
    }
    
    public void setRoleCode(String roleCode) {
        this.roleCode = roleCode;
    }
    
    public String getRoleName() {
        return roleName;
    }
    
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public String getDataScope() {
        return dataScope;
    }
    
    public void setDataScope(String dataScope) {
        this.dataScope = dataScope;
    }
    
    public List<String> getDeptIds() {
        return deptIds;
    }
    
    public void setDeptIds(List<String> deptIds) {
        this.deptIds = deptIds;
    }
    
    public Integer getStatus() {
        return status;
    }
    
    public void setStatus(Integer status) {
        this.status = status;
    }
    
    public Integer getOrderNo() {
        return orderNo;
    }
    
    public void setOrderNo(Integer orderNo) {
        this.orderNo = orderNo;
    }
    
    public LocalDateTime getCreateTime() {
        return createTime;
    }
    
    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }
    
    public LocalDateTime getUpdateTime() {
        return updateTime;
    }
    
    public void setUpdateTime(LocalDateTime updateTime) {
        this.updateTime = updateTime;
    }
    
    public String getCreateBy() {
        return createBy;
    }
    
    public void setCreateBy(String createBy) {
        this.createBy = createBy;
    }
    
    public String getCreateByName() {
        return createdByName;
    }
    
    public void setCreateByName(String createdByName) {
        this.createdByName = createdByName;
    }
    
    public String getUpdateBy() {
        return updateBy;
    }
    
    public void setUpdateBy(String updateBy) {
        this.updateBy = updateBy;
    }
    
    public String getUpdateByName() {
        return updatedByName;
    }
    
    public void setUpdateByName(String updatedByName) {
        this.updatedByName = updatedByName;
    }
    
    public Long getUserCount() {
        return userCount;
    }
    
    public void setUserCount(Long userCount) {
        this.userCount = userCount;
    }
    
    public Integer getPermissionCount() {
        return permissionCount;
    }
    
    public void setPermissionCount(Integer permissionCount) {
        this.permissionCount = permissionCount;
    }
    
    public List<String> getPermissionIds() {
        return permissionIds;
    }
    
    public void setPermissionIds(List<String> permissionIds) {
        this.permissionIds = permissionIds;
    }
    
    public String getOperatorNote() {
        return operatorNote;
    }
    
    public void setOperatorNote(String operatorNote) {
        this.operatorNote = operatorNote;
    }
    
    // ==================== 转换方法 ====================
    
    /**
     * 转换为Role实体
     */
    public com.kexio.user.entity.Role toEntity() {
        com.kexio.user.entity.Role role = new com.kexio.user.entity.Role();
        role.setId(this.roleId);
        role.setTenantId(this.tenantId);
        role.setCode(this.roleCode);
        role.setName(this.roleName);
        role.setDescription(this.description);
        role.setDataScope(this.dataScope);
        role.setStatus(this.status);
        role.setOrderNo(this.orderNo);
        role.setCreateBy(this.createBy);
        role.setUpdateBy(this.updateBy);
        role.setCreateTime(this.createTime);
        role.setUpdateTime(this.updateTime);
        return role;
    }
    
    /**
     * 从Role实体创建DTO
     */
    public static RoleDTO fromEntity(com.kexio.user.entity.Role role) {
        if (role == null) {
            return null;
        }
        
        RoleDTO dto = new RoleDTO();
        dto.setRoleId(role.getId());
        dto.setTenantId(role.getTenantId());
        dto.setRoleCode(role.getCode());
        dto.setRoleName(role.getName());
        dto.setDescription(role.getDescription());
        dto.setDataScope(role.getDataScope());
        dto.setStatus(role.getStatus());
        dto.setOrderNo(role.getOrderNo());
        dto.setCreateBy(role.getCreateBy());
        dto.setUpdateBy(role.getUpdateBy());
        dto.setCreateTime(role.getCreateTime());
        dto.setUpdateTime(role.getUpdateTime());
        return dto;
    }
    
    /**
     * 清除用于创建的ID字段
     */
    public void clearIdsForCreate() {
        this.roleId = null;
        this.createTime = null;
        this.updateTime = null;
        this.createBy = null;
        this.updateBy = null;
        this.userCount = null;
        this.permissionCount = null;
    }
    
    /**
     * 验证必填字段
     */
    public void validate() {
        if (!StringUtils.hasText(this.roleCode)) {
            throw BusinessException.invalidParam("roleCode", "角色编码不能为空");
        }
        if (!StringUtils.hasText(this.roleName)) {
            throw BusinessException.invalidParam("roleName", "角色名称不能为空");
        }
        if (!StringUtils.hasText(this.tenantId)) {
            throw BusinessException.invalidParam("tenantId", "租户ID不能为空");
        }
    }
    
    @Override
    public String toString() {
        return "RoleDTO{" +
                "roleId=" + roleId +
                ", tenantId='" + tenantId + '\'' +
                ", roleCode='" + roleCode + '\'' +
                ", roleName='" + roleName + '\'' +
                ", description='" + description + '\'' +
                ", dataScope='" + dataScope + '\'' +
                ", deptIds=" + deptIds +
                ", status=" + status +
                ", orderNo=" + orderNo +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", userCount=" + userCount +
                ", permissionCount=" + permissionCount +
                '}';
    }
}
